package com.siwei.mes.service.order.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.siwei.mes.common.query.PageQuery;
import com.siwei.mes.common.util.JsonUtils;
import com.siwei.mes.entity.ShxhSynchronizedata;
import com.siwei.mes.entity.UploadLaboratoryEntity;
import com.siwei.mes.entity.erp.Itemorder;
import com.siwei.mes.entity.erp.Rwdextra;
import com.siwei.mes.entity.experiment.Experiment;
import com.siwei.mes.entity.experiment.ExperimentItemorder;
import com.siwei.mes.entity.experiment.ExperimentTask;
import com.siwei.mes.entity.order.Order;
import com.siwei.mes.entity.order.OrderClock;
import com.siwei.mes.entity.order.OrderDetail;
import com.siwei.mes.entity.order.OrderExperiment;
import com.siwei.mes.entity.sync.erp.ErpProject;
import com.siwei.mes.enums.*;
import com.siwei.mes.mapper.ShxhSynchronizedataMapper;
import com.siwei.mes.mapper.erp.ItemorderMapper;
import com.siwei.mes.mapper.experiment.ExperimentItemorderMapper;
import com.siwei.mes.mapper.experiment.ExperimentMapper;
import com.siwei.mes.mapper.experiment.ExperimentTaskMapper;
import com.siwei.mes.mapper.order.OrderClockMapper;
import com.siwei.mes.mapper.order.OrderExperimentMapper;
import com.siwei.mes.mapper.order.OrderMapper;
import com.siwei.mes.mapper.syncErp.ErpProjectMapper;
import com.siwei.mes.service.erp.RwdextraService;
import com.siwei.mes.service.experiment.ExperimentService;
import com.siwei.mes.service.order.OrderDetailService;
import com.siwei.mes.service.order.OrderDynamicService;
import com.siwei.mes.service.order.OrderService;
import com.siwei.mes.service.system.AuthService;
import com.siwei.mes.sync.config.SyncProcessorService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import static com.siwei.mes.common.exception.handler.MessageHandler.assertTrue;

/**
 * 工单(Order)表服务实现类
 *
 * @author makejava
 * @since 2023-12-05 09:31:30
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private OrderDynamicService orderDynamicService;
    @Resource
    private ErpProjectMapper erpProjectMapper;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private AuthService authService;
    @Resource
    private OrderClockMapper orderClockMapper;
    @Resource
    private ExperimentMapper experimentMapper;
    @Resource
    private ExperimentTaskMapper experimentTaskMapper;
    @Resource
    private ExperimentService experimentService;
    @Resource
    private OrderExperimentMapper orderExperimentMapper;
    @Resource
    private ExperimentItemorderMapper experimentItemorderMapper;
    @Resource
    private RwdextraService rwdextraService;
    @Resource
    private ItemorderMapper itemorderMapper;
    @Resource
    private SyncProcessorService syncProcessorService;
    @Resource
    private ShxhSynchronizedataMapper shxhSynchronizedataMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(Order entity) {
        assertTrue(!RoleEnum.CUSTOMER_LEADER.getCode().equals(authService.getLoginUserRole()), "您不是客服组长,不能新建工单!");
        entity.init(true);
        /**通过工程名称查询ERP工程表*/
        ErpProject project = erpProjectMapper.selectByName(entity.getProjectName());
        if (project != null) {
            entity.setProjectId(project.getId());
            entity.setProjectInfo(JsonUtils.beanToObject(project));
        }
        orderMapper.insertSelective(entity);
        /**新增动态*/
        orderDynamicService.insertLog(entity.getId(), DynamicEnum.ORDER_NEW);
        /**新增工单详情*/
        orderDetailService.insertDetail(entity, true);
        return entity.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Order entity) {
        /**通过工程名称查询ERP工程表*/
        ErpProject project = erpProjectMapper.selectByName(entity.getProjectName());
        if (project != null) {
            entity.setProjectId(project.getId());
            entity.setProjectInfo(JsonUtils.beanToObject(project));
        }

        Order order = orderMapper.selectByPrimaryKey(entity.getId());
        assertTrue(order == null, "工单信息不存在");
        assertTrue(order.getOrderStatus().equals(OrderStatusEnum.CANCEL.getCode()), "工单为已作废状态，不能修改！");
        entity.init(false);
        orderMapper.updateByPrimaryKeySelective(entity);
        /**工单详情*/
        orderDetailService.insertDetail(entity, false);
    }

    @Override
    public void delete(Long id) {
        Order order = orderMapper.selectByPrimaryKey(id);
        assertTrue(order == null, "工单信息不存在");
        orderMapper.updateByPrimaryKeySelective(order);
    }

    @Override
    public PageInfo<Order> getPage(PageQuery<Order, Order> query) {
        Order searchParam = query.getParams();
        PageInfo<Order> pageInfo = PageHelper.startPage(query.getPageNum(), query.getPageSize())
                .doSelectPageInfo(() -> orderMapper.getList(searchParam));
        for (Order order : pageInfo.getList()) {
            order.setOrderStatusText(OrderStatusEnum.selectByCode(order.getOrderStatus()).getMessage());
            OrderDetail orderDetail = orderDetailService.payloadDetail(order);
            if (orderDetail != null) {
                order.setOrderDetail(orderDetail);
                order.setDetailInfo(orderDetail.getDetailJson());
                order.setDetailFileInfo(orderDetail.getDetailFile());
            }
        }
        return pageInfo;
    }

    @Override
    public Order loadById(Long id) {
        Order order = orderMapper.loadById(id);
        if (order != null) {
            OrderDetail orderDetail = orderDetailService.payloadDetail(order);
            if (orderDetail != null) {
                order.setOrderDetail(orderDetail);
                order.setDetailInfo(orderDetail.getDetailJson());
                order.setDetailFileInfo(orderDetail.getDetailFile());
            }
            List<OrderClock> list = orderClockMapper.getList(new OrderClock().setOrderId(id));
            if (CollectionUtils.isNotEmpty(list)) {
                order.setClockAddress(list.get(0).getClockAddress());
            }
        }
        return order;
    }

    @Override
    public List<Order> getAll(Order entity) {
        List<Order> list = orderMapper.getList(entity);
        for (Order order : list) {
            OrderDetail orderDetail = orderDetailService.payloadDetail(order);
            if (orderDetail != null) {
                order.setOrderDetail(orderDetail);
                order.setDetailInfo(orderDetail.getDetailJson());
                order.setDetailFileInfo(orderDetail.getDetailFile());
            }
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transfer(Order entity) {
        this.checkRolePermission();
        Order order = orderMapper.selectByPrimaryKey(entity.getId());
        assertTrue(order == null, "工单信息不存在");
        assertTrue(order.getOrderStatus().equals(OrderStatusEnum.CANCEL.getCode()), "工单为已作废状态，不能转派！");
        entity.init(false);
        orderMapper.updateByPrimaryKeySelective(entity);
        orderDynamicService.insertLog(entity.getId(), DynamicEnum.ORDER_TRANSFER);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void finish(Order entity) {
        this.checkRolePermission();
        Order order = orderMapper.loadById(entity.getId());
        assertTrue(order == null, "工单信息不存在");
        entity.init(false);
        entity.setOrderStatus(OrderStatusEnum.FINISH.getCode());
        entity.setFinishServiceTime(new Date());
        entity.setFinishId(authService.getLoginUserId());
        entity.setFinishName(authService.getLoginUserName());
        entity.setFinishTime(new Date());
        if (entity.getGenQuick() != null && entity.getGenQuick() == 1) {
            entity.setIsexcep(Long.valueOf(IsExcepEnum.YES.getCode()));
            this.addQuick(order);
        }
        orderMapper.updateByPrimaryKeySelective(entity);
        orderDynamicService.insertLog(entity.getId(), DynamicEnum.ORDER_FINISH);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void accept(Order entity) {
        this.checkRolePermission();
        Order order = orderMapper.selectByPrimaryKey(entity.getId());
        assertTrue(order == null, "工单信息不存在");
        entity.init(false);
        entity.setStartServiceTime(new Date());
        entity.setOrderStatus(OrderStatusEnum.ACCEPT.getCode());
        entity.setAcceptId(authService.getLoginUserId());
        entity.setAcceptName(authService.getLoginUserName());
        entity.setAcceptTime(new Date());
        orderMapper.updateByPrimaryKeySelective(entity);
        orderDynamicService.insertLog(entity.getId(), DynamicEnum.ORDER_ACCEPT);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refuse(Order entity) {
        this.checkRolePermission();
        Order order = orderMapper.selectByPrimaryKey(entity.getId());
        assertTrue(order == null, "工单信息不存在");
        entity.init(false);
        entity.setOrderStatus(OrderStatusEnum.REFUSE.getCode());
        entity.setRefuseId(authService.getLoginUserId());
        entity.setRefuseName(authService.getLoginUserName());
        entity.setRefuseTime(new Date());
        orderMapper.updateByPrimaryKeySelective(entity);
        orderDynamicService.insertLog(entity.getId(), DynamicEnum.ORDER_REFUSE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(Order entity) {
        this.checkRolePermission();
        Order order = orderMapper.selectByPrimaryKey(entity.getId());
        assertTrue(order == null, "工单信息不存在");
        entity.init(false);
        entity.setOrderStatus(OrderStatusEnum.CANCEL.getCode());
        entity.setCancelId(authService.getLoginUserId());
        entity.setCancelName(authService.getLoginUserName());
        entity.setCancelTime(new Date());
        orderMapper.updateByPrimaryKeySelective(entity);
        orderDynamicService.insertLog(entity.getId(), DynamicEnum.ORDER_CANCEL);
    }

    private void addQuick(Order entity) {
        try {
            log.info("自动生成工单对应的试验台账信息");
            String trwdId = entity.getTrwdId();
            if (StringUtils.isBlank(trwdId)) {
                log.info("erp任务单号为空，不生成对应工单的试验委托");
                return;
            }

            String orderTypeCode = entity.getOrderTypeCode();// 工单类型
            List<String> orderTypeCodeList = new ArrayList<>();
            orderTypeCodeList.add(OrderTypeCodeEnum.ZLSG.getCode());
            orderTypeCodeList.add(OrderTypeCodeEnum.ZLTS.getCode());
            orderTypeCodeList.add(OrderTypeCodeEnum.XCFK.getCode());

            /** 判断哪些工单类型需要新增快检*/
            if (!orderTypeCodeList.contains(orderTypeCode)) {
                log.info("该工单类型不需要新增快检，直接跳过，工单类型：【{}】，工单id：【{}】", orderTypeCode, entity.getId());
                return;
            }
            Rwdextra rwdextra = rwdextraService.selectByFrwdh(Integer.valueOf(trwdId));
            if (rwdextra == null) {
                log.info("ERP任务单信息不存在，直接跳过，任务单id：【{}】", trwdId);
                return;
            }

            Integer frwdh = rwdextra.getFrwdh();//任务单号

            /**这里新增对应的试验台账信息  对应的委托类型应该是现场反馈*/
            Experiment experiment = experimentService.getExperimentInfoByRwdextraToOrder(rwdextra, CheckEnum.QUICK.getCode(), EnturstReasonEnum.XCFK, entity);
            experimentMapper.insertSelective(experiment);

            Long experimentId = experiment.getId();// 试验台账id

            /**新增试验台账对应ERP任务单记录*/
            ExperimentTask experimentTask = new ExperimentTask().setExperimentId(experimentId).setTaskId(frwdh);
            if (experimentTaskMapper.selectOne(experimentTask) == null) {
                experimentTask.setCreateTime(new Date());
                experimentTask.setReadTime(null);
                experimentTaskMapper.insertSelective(experimentTask);
                /**这里新增任务单的关联关系 给对应试验委托的isNewTask改为1*/
                log.info(this.getClass().getName() + "新增任务单给对应isNewTask修改为1");
                experimentMapper.updateIsNewTask(experimentId, 1);

                /**这里判断是否已经上传到协会，如果没有上传到协会就不推送*/
                ShxhSynchronizedata shxhSynchronizedata = shxhSynchronizedataMapper.selectByExperimentIdOne(experimentId);
                if (shxhSynchronizedata != null && shxhSynchronizedata.getSampleId() != null) {
                    log.info(this.getClass().getName() + "新增任务单之后，推送协会！");
                    /**推送到协会，这里新增任务单 状态为自动上传*/
                    syncProcessorService.submitRequest(new UploadLaboratoryEntity().setExperimentId(Collections.singletonList(String.valueOf(experimentId))).setUploadState(1));
                }
            }

            /**新增试验台账对应小票数据*/
            List<Itemorder> itemorderList = itemorderMapper.getList(new Itemorder().setFrwdh(frwdh));
            for (Itemorder itemorder : itemorderList) {
                ExperimentItemorder experimentItemorder = new ExperimentItemorder().setExperimentId(experimentId).setItemorderId(itemorder.getItid());
                experimentItemorderMapper.insertSelective(experimentItemorder);
            }

            /**新增工单和试验台账的关系*/
            OrderExperiment orderExperiment = new OrderExperiment();
            orderExperiment.setOrderId(entity.getId());
            orderExperiment.setExperimentId(experimentId);
            if (orderExperimentMapper.selectOne(orderExperiment) == null) {
                orderExperimentMapper.insertSelective(orderExperiment);
            }
        } catch (Exception e) {
            log.error("工单类型新增试验台账失败，失败原因：【{}】", e.getMessage(), e);
            /**手动回滚事务*/
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    public void checkRolePermission() {
        List<String> rolePermission = new ArrayList<>();
        rolePermission.add(RoleEnum.CUSTOMER_LEADER.getCode());
        rolePermission.add(RoleEnum.CUSTOMER_INSPECTOR.getCode());
        assertTrue(!rolePermission.contains(authService.getLoginUserRole()), "您暂无权限操作");
    }
}
